home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2004 #11
/
Amiga Plus CD - 2004 - No. 11.iso
/
AmiSoft
/
Text
/
print
/
HPDJ900Src.lha
/
compression.c
next >
Wrap
C/C++ Source or Header
|
2004-05-21
|
6KB
|
229 lines
/*
* $Id: compression.c 44.1 1999/09/02 11:08:00 olsen Exp olsen $
*
* :ts=4
*
* COPYRIGHT:
*
* Unless otherwise noted, all files are Copyright (c) 1999 Amiga, Inc.
* All rights reserved.
*
* DISCLAIMER:
*
* This software is provided "as is". No representations or warranties
* are made with respect to the accuracy, reliability, performance,
* currentness, or operation of this software, and all use is at your
* own risk. Neither Amiga nor the authors assume any responsibility
* or liability whatsoever with respect to your use of this software.
*
*/
#include "global.h"
/*****************************************************************************/
LONG StripWhiteSpace(UBYTE * source,LONG size)
{
LONG i;
/* Optimization: strip all trailing zero bytes. */
for(i = size ; i > 0 ; i--)
{
if(source[i-1] != 0)
{
size = i;
break;
}
}
return(size);
}
/*****************************************************************************/
/* PCL compression method #2, also known as "TIFF packbits" or ByteRun1. */
LONG CompressMethod2(UBYTE * src, UBYTE * dest, LONG count)
{
UBYTE * last = dest + count;
UBYTE * outptr;
UBYTE * inptr;
UBYTE * saveptr;
UBYTE data; /* data byte */
UBYTE lastbyte; /* last byte */
LONG repcount; /* repeat count */
LONG litcount; /* literal count */
inptr = src;
outptr = dest;
/* Start loop through data. Check for possible repeat at beginning. */
while(count > 0)
{
/* get value to work with */
data = (*inptr++);
count--;
/* no repeat count yet */
repcount = 0;
/* Check for repeat, since we are not in the middle
* of a literal run, it does not have to be more than
* two bytes of similar data.
*/
while(count > 0 && (*inptr) == data)
{
repcount++;
inptr++;
count--;
}
/* Now, if we are out of data (count == 0), then
* if the repeated byte was zero, then ignore it
* completely (don't bother outputing the trailing zeros).
*/
if(count == 0 && data == 0)
break; /* done */
/* If there was a repeat (repcount > 0), then we
* can output the command here, otherwise, we
* need to go into literal run mode.
*
* Note: This is a while loop because the repeat count
* may actually be greater than 127.
*/
if(repcount >= 1) /* repeat mode */
{
while(repcount > 127)
{
if(outptr + 2 > last)
return(-1);
(*outptr++) = 129; /* count 127 */
(*outptr++) = data; /* value */
repcount -= 128; /* offset */
}
if(repcount > 0)
{
if(outptr + 2 > last)
return(-1);
(*outptr++) = 256 - repcount; /* count */
(*outptr++) = data; /* value */
/* Now pop to the top of the loop
* looking for more repeat counts.
*/
continue; /* top of loop */
}
/* Special case. If we have arrived at this point,
* then repcount is now equal to 0. This means
* that when we entered this section, repcount
* was a multiple of 128 (i.e. 128 :-).
*
* This means that there were 129 identical bytes,
* so the output does a replicate of 127 which
* gives 128 bytes, and we now have one byte left
* over which should NOT be output as a repeat
* run, rather it should be merged into the following
* literal run (if it exists).
*
* So, we will simply fall thru to the next section
* of code which assumes that we are working on
* a literal run.
*/
}
/* Literal run. At this point, the current data byte
* does NOT match the following byte. We will transfer
* these non-identical bytes until:
*
* 1) we run out of input data (count == 0).
* 2) we run out of room in this output block (128)
* 3) we come across a value which occurs at least
* three times in a row. A value occuring only
* twice in a row does NOT justify dropping
* out of a literal run.
*
* Special case: If we run out of room in the output block
* (which is 128 bytes), the last two values are the same,
* AND there is more input, it makes sense to restart
* the repeat detector in case the following bytes are
* repeats of the two. A simple check of the following
* byte will determine this.
* (This case falls out with the test for triples below).
*
* Special case: If we run out of room in the output block
* (which is 128 bytes), the last value is the same as
* the next one on the input, then it is better to let
* that byte be used in a possible replicate run following
* the literal run. If the last byte matches ONLY the
* following byte, (and not the one after that, it is
* a wash, but for best results, we will test the
* following two bytes.
*/
litcount = 0;
saveptr = outptr++; /* save location of the command byte */
if(outptr + 1 > last)
return(-1);
(*outptr++) = data; /* save the first byte. */
lastbyte = data; /* remember for testing */
while(count > 0 && litcount < 127)
{
data = (*inptr++);
count--;
litcount++;
if(outptr + 1 > last)
return(-1);
(*outptr++) = data;
/* Test to see if this byte matched the last one.
* If so, check the next one for a triple.
*/
if(lastbyte == data && count > 0 && (*inptr) == data)
{
/* We have a triple, adjust accordingly.
* Add two bytes back onto the input.
*/
count += 2;
inptr -= 2;
outptr -= 2;
litcount -= 2;
break; /* out of loop */
}
lastbyte = data; /* save data byte */
}
/* Check the special case number 2 above. */
if(litcount == 127 && count > 1 && data == (*inptr) && data == inptr[1])
{
/* Restore the last byte to the input stream */
count += 1;
inptr -= 1;
outptr -= 1;
litcount -= 1;
}
/* Save the literal run count. */
(*saveptr) = litcount;
}
return(outptr - dest);
}